#!/usr/bin/python

from testplug import PluginTest
from yapsy.PluginManager import PluginManager

import pygame
import tiledtmxloader

def load_hero(start_pos_x, start_pos_y, tile_width, tile_height):
    """
    Loads the hero sprite.
    """
    image = pygame.image.load('arch-mage.png')
    #rect = image.get_rect()
    #rect.midbottom = (36,  36)
    return Creature(image, start_pos_x, start_pos_y, tile_width, tile_height)


class Creature(tiledtmxloader.helperspygame.SpriteLayer.Sprite):
    """
    This is a dynamic sprite. Imagine it is an animal or hero or
    similar moving around the world.
    """

    def __init__(self, img, start_pos_x, start_pos_y, tile_width, tile_height):
        """
        Constructor.
        """
        super(Creature, self).__init__(img, img.get_rect())
        self.velocity_x = tile_width
        self.velocity_y = tile_height
        self.position_x = start_pos_x
        self.position_y = start_pos_y
        self.rect.center = (self.position_x * self.velocity_x + self.velocity_x / 2, self.position_y * self.velocity_y + self.velocity_y / 2)

    def update(self, direction):
        """
        Update the movement of the dude.
        """
        if not direction:
            self.position_y -= 1
        elif direction == 1:
            self.position_y += 1
        elif direction == 2:
            self.position_x -= 1
        elif direction == 3:
            self.position_x += 1
        self.rect.center = (self.position_x * self.velocity_x + self.velocity_x / 2, self.position_y * self.velocity_y + self.velocity_y / 2)

class NoFontError(Exception):
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr(self.value)

def main():
    # Define some colors
    black = (   0, 0, 0)
    white = ( 255, 255, 255)
    green = (   0, 255, 0)
    red = ( 255, 0, 0)

    pygame.init()

    if pygame.font.get_init() == False:
        raise NoFontError("PyGame fonts not initialized!")

    # Set the height and width of the screen
    size = [800, 600]
    screen = pygame.display.set_mode(size) # , pygame.FULLSCREEN)

    pygame.display.set_caption("TrailReach")

    #Loop until the user clicks the close button.
    done = False

    # Used to manage how fast the screen updates
    clock = pygame.time.Clock()

    pygame.key.set_repeat(200, 100)

    # Test loading the map
    world_map = tiledtmxloader.tmxreader.TileMapParser().parse_decode("dry_test.tmx")

    # load the images using pygame
    resources = tiledtmxloader.helperspygame.ResourceLoaderPygame()
    resources.load(world_map)

    # prepare map rendering
    assert world_map.orientation == "orthogonal"

    # renderer
    renderer = tiledtmxloader.helperspygame.RendererPygame()

    # create hero sprite
    # use floats for hero position
    hero_pos_x = 0
    hero_pos_y = 0
    hero = load_hero(hero_pos_x, hero_pos_y, world_map.tilewidth, world_map.tileheight)

    # cam_offset is for scrolling
    cam_world_pos_x = hero.position_x * world_map.tilewidth + world_map.tilewidth / 2
    cam_world_pos_y = hero.position_y * world_map.tileheight + world_map.tileheight / 2

    # set initial cam position and size
    renderer.set_camera_position_and_size(cam_world_pos_x, cam_world_pos_y,\
        size[0], size[1])

    # retrieve the layers
    sprite_layers = tiledtmxloader.helperspygame.get_layers_from_map(resources)

    # add the hero the the right layer, it can be changed using 0-9 keys
    sprite_layers[1].add_sprite(hero)

    event_layer = None
    for sprite_layer in sprite_layers:
        if sprite_layer.is_object_group:
            if sprite_layer.name == "Events":
                event_layer = sprite_layer

    if event_layer == None:
        raise NoFontError("No Event Layer!")

    test_font = pygame.font.Font(None, 36)

    # Create plugin manager
    manager = PluginManager(categories_filter={ "PluginTest": PluginTest})
    manager.setPluginPlaces(["plugins"])

    # Load plugins
    manager.locatePlugins()
    manager.loadPlugins()

    plugintests = {}

    for plugin in manager.getPluginsOfCategory("PluginTest"):
        print "XXX"
        plugintests[plugin.plugin_object.name] = plugin.plugin_object

    # -------- Main Program Loop -----------
    while not done:
        for event in pygame.event.get(): # User did something
            if event.type == pygame.QUIT: # If user clicked close
                done = True # Flag that we are done so we exit this loop
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP:
                    hero.update(0)
                if event.key == pygame.K_DOWN:
                    hero.update(1)
                if event.key == pygame.K_LEFT:
                    hero.update(2)
                if event.key == pygame.K_RIGHT:
                    hero.update(3)
                if event.key == pygame.K_q:
                    done = True

        cam_world_pos_x = hero.position_x * world_map.tilewidth + world_map.tilewidth / 2
        cam_world_pos_y = hero.position_y * world_map.tileheight + world_map.tileheight / 2
        renderer.set_camera_position(cam_world_pos_x, cam_world_pos_y)

        # Set the screen background
        screen.fill(black)

        # render the map
        for sprite_layer in sprite_layers:
            if sprite_layer.is_object_group:
                # we don't draw the object group layers
                # you should filter them out if not needed
                continue
            else:
                renderer.render_layer(screen, sprite_layer)

        #font_surface = test_font.render("This is a test", True, (255,255,255))

        #screen.blit(font_surface, (0,0))

        for object in event_layer.objects:
            if hero.position_x == object.x / world_map.tilewidth and hero.position_y == object.y / world_map.tileheight:
                #teststring = ast.literal_eval()
                teststring = getattr(plugintests["TestPlugin"], object.properties["Start"])()
                #eval(object.properties["Start"])

                font_surface = test_font.render(teststring, True, (255,255,255))
                screen.blit(font_surface, (400,300))

        # Go ahead and update the screen with what we've drawn.
        pygame.display.flip()

        # Limit to 20 frames per second
        clock.tick(20)

    # Be IDLE friendly. If you forget this line, the program will 'hang'
    # on exit.
    pygame.quit()

if __name__ == '__main__':
    main()
